<?php
declare(strict_types=1);
/**
 * MineAdmin is committed to providing solutions for quickly building web applications
 * Please view the LICENSE file that was distributed with this source code,
 * For the full copyright and license information.
 * Thank you very much for using MineAdmin.
 *
 * @Author X.Mo<root@imoi.cn>
 * @Link   https://gitee.com/xmo/MineAdmin
 */

namespace App\CustHub\Service;


use App\CustHub\Mapper\ChApiDocCateMapper;
use Mine\Abstracts\AbstractService;
use Mine\Annotation\DeleteCache;
use Mine\Annotation\Transaction;
use Mine\Exception\NormalStatusException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

/**
 * 文章分类服务类
 */
class ChApiDocCateService extends AbstractService
{
    /**
     * @var ChApiDocCateMapper
     */
    public $mapper;


    public function __construct(
        ChApiDocCateMapper $mapper,
    )
    {
        $this->mapper = $mapper;
    }

    /**
     * 获取树列表
     * @param array|null $params
     * @param bool $isScope
     * @return array
     */
    public function getTreeList(?array $params = null, bool $isScope = true): array
    {
        if ($params['select'] ?? null) {
            $params['select'] = explode(',', $params['select']);
        }
        $params['recycle'] = false;
        return $this->mapper->getTreeList($params, true, 'id', 'parent_id');
    }

    /**
     * 从回收站获取树列表
     * @param array|null $params
     * @param bool $isScope
     * @return array
     */
    public function getTreeListByRecycle(?array $params = null, bool $isScope = true): array
    {
        if ($params['select'] ?? null) {
            $params['select'] = explode(',', $params['select']);
        }
        $params['recycle'] = true;
        return $this->mapper->getTreeList($params, true, 'id', 'parent_id');
    }

    /**
     * 获取前端选择树
     * @return array
     */
    public function getSelectTree(): array
    {
        return $this->mapper->getSelectTree();
    }

    /**
     * 新增数据
     * @param array $data
     * @return int
     */
    #[DeleteCache('api_doc_cate:list'),Transaction]
    public function save(array $data): int
    {
        $data = $this->handleData($data);
        $cateId = $this->mapper->save($data);
        return $cateId;
    }

    /**
     * 更新
     * @param int $id
     * @param array $data
     * @return bool
     */
    #[DeleteCache('api_doc_cate:list'),Transaction]
    public function update(mixed $id, array $data): bool
    {
        $data = $this->handleData($data);
        $rst = $this->mapper->update($id, $data);
        $level = $data['level'].','.$id;
        $this->updateChild($id,$level);
        return $rst;
    }

    private function updateChild($pid,$level)
    {
        $childList = $this->mapper->model::where('parent_id', $pid)->get();
        foreach ($childList as $item){
            $this->mapper->update($item['id'], ['level'=>$level]);
            $this->updateChild($item['id'],$level.','.$item['id']);
        }
    }

    /**
     * 处理数据.
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    protected function handleData(array $data): array
    {
        $pid = $data['parent_id'] ?? 0;

        if (isset($data['id']) && $data['id'] == $pid) {
            throw new NormalStatusException('错误的上级分类', 500);
        }

        if ($pid === 0) {
            $data['level'] = $data['parent_id'] = '0';
        } else {
            $parentInfo = $this->read($data['parent_id']);
            if(isset($data['id']) && $parentInfo['parent_id'] == $data['id']){
                throw new NormalStatusException('错误的上级分类', 500);
            }
            $data['level'] = $this->read($data['parent_id'])->level . ',' . $data['parent_id'];
        }

        return $data;
    }

    /**
     * 真实删除数据，跳过存在子节点的数据
     * @return array
     */
    #[DeleteCache('article_cate:list')]
    public function realDel(array $ids): ?array
    {
        // 存在子节点，跳过的数据
        $ctuIds = [];
        if (count($ids)) foreach ($ids as $id) {
            if (!$this->checkChildrenExists( (int) $id)) {
                $this->mapper->realDelete([$id]);
            } else {
                array_push($ctuIds, $id);
            }
        }
        return count($ctuIds) ? $this->mapper->getTreeName($ctuIds) : null;
    }

    /**
     * 检查子节点是否存在
     * @param int $id
     * @return bool
     */
    public function checkChildrenExists(int $id): bool
    {
        return $this->mapper->checkChildrenExists($id);
    }

    /**
     * 获取分类列表
     * @return array
     */
    public function getCateList(): array
    {
        $tree = $this->mapper->getCateList();
        return $tree;
    }
}
